{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 作业二"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 为MNIST数据集构建一个分类器，并在测试集上达成超过90%的精度 10分\n",
    "# 提示：KNeighborsClassifier对这个任务非常有效，你只需要找到合适的超参数即可，可对weights和n_neighbors这两个超参数进行网格搜索"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 读取MNIST数据集，创建训练集和测试集\n",
    "import numpy as np\n",
    "import matplotlib\n",
    "import matplotlib.pyplot as plt\n",
    "from sklearn.datasets import fetch_mldata\n",
    "import matplotlib.pyplot as plt\n",
    "from sklearn.metrics import confusion_matrix\n",
    "from sklearn.model_selection import cross_val_score\n",
    "from sklearn.neighbors import KNeighborsClassifier\n",
    "from sklearn.metrics import precision_score, recall_score\n",
    "from sklearn.model_selection import GridSearchCV\n",
    "\n",
    "# 内嵌绘图\n",
    "%matplotlib inline  \n",
    "mnist = fetch_mldata('MNIST original', data_home='./')\n",
    "X,y = mnist['data'], mnist['target']\n",
    "X_train, X_test, y_train, y_test = X[:60000], X[60000:], y[0:60000], y[60000:] # 切分训练集和测试集\n",
    "shuffle_index = np.random.permutation(60000)\n",
    "X_train, y_train = X_train[shuffle_index], y_train[shuffle_index] # 随机下标分配训练集\n",
    "\n",
    "# 以9为例，进行训练\n",
    "y_train_9 = (y_train==9)\n",
    "y_test_9 = (y_test==9)\n",
    "\n",
    "def show_img1(X,i):\n",
    "    some_digit = X[i]\n",
    "    some_digit_image = some_digit.reshape(28,28)  # reshape,imshow  显示图片\n",
    "    plt.imshow(some_digit_image, cmap=matplotlib.cm.binary)\n",
    "    plt.show()\n",
    "    \n",
    "def show_img2(X,i):\n",
    "    some_digit = X[i]\n",
    "    some_digit_image = some_digit.reshape(28,28)\n",
    "    plt.imshow(some_digit_image, cmap=matplotlib.cm.binary, interpolation='nearest') # nearest 最邻近插值法，输入目标图像和行缩放、纵缩放倍数\n",
    "    plt.axis('off')\n",
    "    plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([0., 9., 8., 0., 3., 1., 6., 1., 2., 3.])"
      ]
     },
     "execution_count": 7,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "y_train[10:20] "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAAOcAAADnCAYAAADl9EEgAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAADh0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uMy4yLjEsIGh0dHA6Ly9tYXRwbG90bGliLm9yZy+j8jraAAAG9UlEQVR4nO3dTYjUdRzH8V0RD4aIpgiCJ0VBDwU+BIJKC9ohRMsnWEIEQfTgYSXwiQqC6iLoSSiik3hYsUMQqYhevEiePHjQQHxARRRKUZZa2E7ddr5/mnHdz8y+Xsf98P/PaLz9Qz9mtn9sbKwPyDNtst8AMD5xQihxQihxQihxQqjpDbv/lQsTr3+8H3pyQihxQihxQihxQihxQihxQihxQihxQihxQihxQihxQihxQihxQihxQihxQihxQihxQihxQihxQihxQihxQihxQihxQihxQihxQihxQihxQihxQihxQihxQqimXwFIG0ZGRsr98uXLLbevv/66vPb3339v6z3957PPPiv3L7/8suW2ePHi8tpp0/xb/yb524RQ4oRQ4oRQ4oRQ4oRQ4oRQ4oRQ/WNjY9VejlPVy5cvy33Xrl3lfuHChTf5dt6ax48fl/uCBQve0jvpOf3j/dCTE0KJE0KJE0KJE0KJE0KJE0KJE0I55xzHX3/9Ve5Nn4n89ddf237t5cuXl/uRI0fKvenzoH/88cf/fk//+fjjj8t906ZN5X7w4MG2X7vHOeeEbiJOCCVOCCVOCCVOCCVOCOWrMcdx9uzZcu/kqKSvr69v9+7dLbcvvviivPbbb78t906OSpo0/bkvXrxY7qOjo+U+NDT0v99TL/PkhFDihFDihFDihFDihFDihFDihFBT8iNjz58/L/cNGzaU+61btzp6/eoc9e7du+W1x48fL/f58+eX+4EDB8p9yZIlLbd9+/aV1zb96sMZM2aUe3WGe+jQofLaLucjY9BNxAmhxAmhxAmhxAmhxAmhxAmhpuTnOc+dO1funZ5jnjp1qtx37tzZcvv88887eu2TJ0+W++DgYNv3HhgYKPdt27aV+/Xr18v92LFjLbeVK1eW1zadTXcjT04IJU4IJU4IJU4IJU4IJU4IJU4I1bPnnNXnVC9dujShr/3JJ5+U+7Rprf9NXLt2bXnt8PBwuTedB3Zi4cKF5f7VV1+V++bNm8v977//brnt37+/vLbpv+miRYvKPZEnJ4QSJ4QSJ4QSJ4QSJ4QSJ4QSJ4Tq2e+trX5P5dKlSzu6d9NZ4pUrV8p91qxZHb1+t/r555/Lffv27W3fu+napvPhSeZ7a6GbiBNCiRNCiRNCiRNCiRNC9exHxibSsmXLyn2qHpU0+eijj8r9gw8+aLk1fa3mixcvyr36OFpfX/OvJ5wMnpwQSpwQSpwQSpwQSpwQSpwQSpwQyjlnGz799NPJfgtd6Z133in3devWtdyazjmbvhrzwYMH5b548eJynwyenBBKnBBKnBBKnBBKnBBKnBBKnBCqZ885z5w5M2H3TjwT6wWDg4MttxMnTrzFd5LBkxNCiRNCiRNCiRNCiRNCiRNCiRNC9ew556NHjyb7LUBHPDkhlDghlDghlDghlDghlDghlDghVM+ec65atarl9uOPP3Z07xs3bpT7e++919H9oa/PkxNiiRNCiRNCiRNCiRNCiRNC9exRysDAwITd++rVq+W+d+/eCXvtbvbnn3+W+549e9q+94oVK8p97ty5bd97snhyQihxQihxQihxQihxQihxQihxQqiePeecPr31H23mzJnlta9fvy73V69elfvo6Gi5V++tlz18+LDcb9682fa916xZU+5z5sxp+96TxZMTQokTQokTQokTQokTQokTQokTQvWPjY1Vezl2qx07dpT7+fPnO7r/vXv3yn3RokUd3T/V/fv3y33jxo3lfufOnZbbhx9+WF47PDxc7u+++265T7L+8X7oyQmhxAmhxAmhxAmhxAmhxAmhxAmhpuYHCydYr55zXrt2rdybvq+3Osdscvjw4XIPP8dsiycnhBInhBInhBInhBInhBInhJqSHxn75Zdfyn3r1q0d3X/BggXl/ttvv7Xc3n///Y5eu8mjR4/K/Ycffmi5fffdd+W1//zzT7k3fSXp6dOnW25btmwpr509e3a5h/ORMegm4oRQ4oRQ4oRQ4oRQ4oRQ4oRQU/Kcc2RkpNyHhobK/fvvv+/o9efNm9dy++abb8prnz17Vu4//fRTuTf9+sInT56Ue2X16tXlfvTo0XLv9Hy5iznnhG4iTgglTgglTgglTgglTgglTgg1Jc85m9y+fbvc169fX+5Pnz59k28nRtM5ZtPnPQcGBt7k2+klzjmhm4gTQokTQokTQokTQokTQokTQjnnhMnnnBO6iTghlDghlDghlDghlDghlDghlDghlDghlDghlDghlDghlDghlDghlDghlDghlDghlDghlDghlDghlDghlDghlDghlDghlDghlDghlDghlDghlDghlDgh1PSGfdxfTQZMPE9OCCVOCCVOCCVOCCVOCCVOCPUvOMopOWdXmnoAAAAASUVORK5CYII=\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "show_img2(X,11)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "show_img2(X_train,10)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(784,)"
      ]
     },
     "execution_count": 10,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "test_digit = X_train[10]\n",
    "test_digit.reshape(1,784)\n",
    "test_digit.shape"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(1, 784)"
      ]
     },
     "execution_count": 11,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "test_digit = X_train[13:14]\n",
    "test_digit.shape"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [],
   "source": [
    "test_digits = X_train[10:20]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "KNeighborsClassifier(algorithm='auto', leaf_size=30, metric='minkowski',\n",
       "           metric_params=None, n_jobs=1, n_neighbors=5, p=2,\n",
       "           weights='uniform')"
      ]
     },
     "execution_count": 13,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "knn_clf = KNeighborsClassifier() # K近邻算法\n",
    "knn_clf.fit(X_train, y_train_9)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([False,  True, False, False, False, False, False, False, False,\n",
       "       False])"
      ]
     },
     "execution_count": 14,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "knn_clf.predict(test_digits) # 预测测试集中每一个样本的标签"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([False])"
      ]
     },
     "execution_count": 15,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "knn_clf.predict(test_digit)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "train_score = cross_val_score(knn_clf, X_train, y_train_9, cv=5, scoring='accuracy')  # 交叉验证"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "train_score.mean()  # 查看均值"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from sklearn.model_selection import cross_val_predict\n",
    "\n",
    "y_train_pred = cross_val_predict(knn_clf, X_train, y_train_9, cv=5, verbose=3)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "confusion_matrix(y_train_9, y_train_pred) # 混淆矩阵"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "print('精度：{0:.2f} %'.format(100*precision_score(y_train_9, y_train_pred)))\n",
    "print('召回率：{0:.2f} %'.format(100*recall_score(y_train_9, y_train_pred)))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 尝试用knn_clf.predict\n",
    "%%time\n",
    "y_test_pred = knn_clf.predict(X_test)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "confusion_matrix(y_test_9, y_test_pred)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "print('精度：{0:.2f} %'.format(100*precision_score(y_test_9, y_test_pred)))\n",
    "print('召回率：{0:.2f} %'.format(100*recall_score(y_test_9, y_test_pred)))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 网格\n",
    "%%time\n",
    "param_grid = [{'weights': [\"uniform\", \"distance\",], 'n_neighbors': [2, 4, 6]}]\n",
    "knn_clf = KNeighborsClassifier()\n",
    "grid_search = GridSearchCV(knn_clf, param_grid, cv=5, verbose=3)\n",
    "grid_search.fit(X_train, y_train_9)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 查看最优参数\n",
    "grid_search.best_params_"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "grid_search.best_estimator_"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "grid_search.best_score_"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "grid_search.predict(test_digit)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%%time\n",
    "y_test_pred = grid_search.predict(X_test)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "confusion_matrix(y_test_9, y_test_pred)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "print('精度：{0:.2f} %'.format(100*precision_score(y_test_9, y_test_pred)))\n",
    "print('召回率：{0:.2f} %'.format(100*recall_score(y_test_9, y_test_pred)))"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.4"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
